home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / batchut / appenv21.zip / APPENV.C next >
Text File  |  1989-10-20  |  5KB  |  152 lines

  1. /*
  2.  *  APPENV - APPend to ENVironment  --2.1--  Copyright (c) Mark Lord, 1989
  3.  *
  4.  *  Feel free to copy, use and/or modify this for any non-commercial
  5.  *  purpose(s).  Please keep this copyright header in place.
  6.  *
  7.  *  Compile this under TINY model of Turbo-C 2.0 and use the /t with TLINK
  8.  *  to produce a small .COM file.
  9.  */
  10.  
  11. #include <dos.h>
  12. #include <ctype.h>
  13.  
  14. char cant_find_env [] = "APPENV: can't find master environment\n$";
  15.  
  16. char helptext [] =
  17.  "\r\nAPPENV  --  APPend to ENVironment  ---  Version 2.1 (c) 1989 by Mark Lord\r\n\n"\
  18.  "This command allows appending data to the end of an existing  environment\r\n"\
  19.  "variable, such as PATH.     Usage:     APPENV <var>=<data>\r\n"\
  20.  "Where  <var> is the name of the environment variable,  and  <data> is the\r\n"\
  21.  "value to be assigned to it.   If <var> does not already exist, it will be\r\n"\
  22.  "created with a value of <data>,  otherwise <data> will be appended to the\r\n"\
  23.  "current value of <var>.  If no <data> is given, then <var> will be erased\r\n"\
  24.  "from the environment.   If there is not enough environment space left for\r\n"\
  25.  "<data>,  it will be truncated and a beep! will be sounded on the speaker.\r\n"\
  26.  "Works only with DOS 3.3 or higher.\r\n$";
  27.  
  28. void quit (char *text)
  29. {
  30.         /* Output the help text and exit with ERRORLEVEL=2. */
  31.  
  32.         union REGS regs;
  33.         regs.h.ah = 9;
  34.     regs.x.dx = FP_OFF (text);
  35.         intdos (®s, ®s);
  36.         exit (2);
  37. }
  38.  
  39. void main ()
  40. {
  41.     int size, env_para;
  42.         unsigned psp, far *tmp;
  43.         char far *env, far *e, far *p, varbuf[1024], *v;
  44.  
  45.         /* _psp is our PSP.  Follow the "parent" links back
  46.            until we find a PSP for COMMAND.COM, which has
  47.            a parent link that points at itself. */
  48.  
  49.         psp = _psp;
  50.         while (psp != *(tmp = MK_FP(psp,22)))
  51.                 psp = *tmp;
  52.  
  53.         /* Now get the address of COMMAND.COM's environment block
  54.            from its PSP. */
  55.  
  56.     if (!(env_para = *(unsigned far *)MK_FP(psp,44)))
  57.         quit (cant_find_env);
  58.  
  59.     env = MK_FP(env_para,0);
  60.  
  61.         /* Get the block size from the MCB which immediately
  62.            preceeds the environment block.  This is a paragraph count,
  63.            which must be multiplied by 16 to get a byte count. */
  64.  
  65.         size = 16 * *(int far *) MK_FP(FP_SEG(env)-1,3);
  66.  
  67.         /* Back to our own PSP again, where our command line
  68.            parameters are stored, terminated by a carriage return. */
  69.  
  70.         p = MK_FP(_psp,129);
  71.  
  72.         /* Ignore leading spaces (there is usually one or more),
  73.            and give the user some help if there is nothing else there. */
  74.  
  75.         while (*p == ' ') ++p;
  76.     if ((*p == '\r') || (*p == '=')) quit (helptext);
  77.  
  78.         /* Now some tricky parsing to extract the variable name and
  79.            equal sign into varbuf[], ignoring spaces between the name
  80.            and the equal sign.  If there is no equal sign, give the
  81.            user some help instead. */
  82.  
  83.         v = (char *) &varbuf;
  84.         while ((*p != '\r') && ((*v = toupper(*p++)) != '='))
  85.                 if (*v != ' ') ++v;
  86.     if (*v != '=') quit (helptext);
  87.         *++v = '\0';
  88.  
  89.         /* The outer loop below searches for an existing environment
  90.            variable of the same name as we have in varbuf[]. */
  91.  
  92.         while (*env) {
  93.  
  94.                 /* Compare current env variable with varbuf[]. */
  95.  
  96.                 e = env;
  97.                 v = (char *) &varbuf;
  98.         while (*e == *v) ++v, ++e;
  99.  
  100.                 /* If they matched, copy old value into varbuf[], and
  101.                    then delete it from the environment.  Otherwise,
  102.                    move env to point at the next environment variable
  103.                    for the next iteration of our main loop. */
  104.  
  105.         if (!*v) {
  106.                         while (*v++ = *e++);
  107.                         if (*e)
  108.                                 while ((--size) && (*env++ = *e++) || (*e));
  109.                         *env = '\0';
  110.                 } else
  111.                         while ((--size) && (*env++));
  112.         }
  113.  
  114.         /* If no data was entered after the equal sign, then we are
  115.            supposed to delete the variable, which we've already done.
  116.            Otherwise, some work remains.  We have to re-add the variable
  117.            at the end of the environment with its old value, and then
  118.            append the new value after it. */
  119.  
  120.         if (*p != '\r') {
  121.  
  122.                 /* Copy name, equal sign, and old value into env. */
  123.  
  124.                 v = (char *) &varbuf;
  125.                 while (*env = *v++) ++env, --size;
  126.  
  127.                 /* Now append new data to the end of the old value. */
  128.  
  129.                 while ((--size) && ((*env++ = *p++) != '\r'));
  130.  
  131.                 /* Ensure the environment is properly terminated with
  132.            two consecutive zeros. */
  133.  
  134.                 *env = '\0';
  135.                 *--env = '\0';
  136.  
  137.                 /* If we ran out of space somewhere above, sound a beep
  138.                    sequence to alert the user that something is fishy. */
  139.  
  140.                 if (size <= 0) {
  141.                         for (size = 3; (--size);) {
  142.                                 sound (650);
  143.                                 delay (60);
  144.                                 nosound ();
  145.                                 delay (50);
  146.                         };
  147.                         exit (1);
  148.                 }
  149.         }
  150. }
  151.  
  152.